package or.bhavani.wordhistogram;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
import java.util.Vector;

import javax.naming.ldap.SortKey;
import javax.net.ssl.HostnameVerifier;

class HistEntryComparator implements Comparator<Map.Entry<String, Integer>>{

	@Override
	public int compare(Entry<String, Integer> arg0, Entry<String, Integer> arg1) {
		return arg0.getKey().compareTo(arg1.getKey());
	}
	
}
public class WordHistogram {
	private  Hashtable<String, Integer> wordCount;

	public Hashtable<String, Integer> getWordCount() {
		return wordCount;
	}


	public WordHistogram(){
		wordCount =  new Hashtable<String, Integer>();
	}
	
	// rename to computeHistogram, becuase that's what it's doing
	public Hashtable computeHistogram(){
		try {

			// it's better not to hardcode the file name.  Please pass as a param either to constructor
			// or this method.  I would prefer passing to the constructor
			BufferedReader read = new BufferedReader(new FileReader("/Users/bhavaniyarlagadda/Documents/Durga/Alogorithms/Alogorithms/src/or/bhavani/wordhistogram/durga"));

			String s;			
			System.out.println("Reading file  durga");

			while ((s = read.readLine()) != null) {
				// todo: indentation is off
				if(	wordCount.containsKey(s)){
					wordCount.put(s, wordCount.get(s) + 1);  // remove the extra line below
					
				}
				else{
					wordCount.put(s, 1); // remove the extra line below

				}
			}	

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		return wordCount;

	}
	public static void printHashTable( Hashtable<String,Integer> hashtable){
		Enumeration<String> keys = hashtable.keys() ;
		while(keys.hasMoreElements()) {  
			String key = keys.nextElement();
			System.out.println(key+" "+ hashtable.get(key));
		}

	}
	// rename to printHistogramSortedByKeys, because underneath you could be using a hashmap
	// or whatever collection.  For the user of this class, he wants to print histogram.  He
	// doesn't care whether it's based on hashtable or whatever collection.
	public void printHastableBySortedKeys(){

		// rename A to keys for readability
		ArrayList<String>A = new ArrayList<String>( wordCount.keySet());
		Collections.sort(A);

		for (int i = 0; i < A.size(); i++) {
			String key =  A.get(i);
			System.out.println( key+" "+wordCount.get(key));
		}
		
	}
	
	// another variation of above function using a treeset.  Treeset maintains
	// it's values in a sorted fashion
	public void printHistogramBySortedKeysV2() {
		TreeSet<String> keySet = new TreeSet<String>(wordCount.keySet());
		Iterator<String> keyIt = keySet.iterator();
		while (keyIt.hasNext()) {
			String key = keyIt.next();
			System.out.println( key+" "+wordCount.get(key));
		}
	}

	// Out of the above this is most efficient
	public void printHistogramBySortedKeysV3() {
		TreeSet<Map.Entry<String,Integer>> entrySet = 
				new TreeSet<Map.Entry<String,Integer>>(new HistEntryComparator());
		entrySet.addAll(wordCount.entrySet());
		Iterator<Map.Entry<String,Integer>> entryIt = entrySet.iterator();
		while (entryIt.hasNext()) {
			Map.Entry<String,Integer> entry = entryIt.next();
			System.out.println( entry.getKey()+" "+entry.getValue());
		}
	}
	
	public static void main(String args[]) {
		WordHistogram histogram = new WordHistogram();
		
		histogram.computeHistogram();
		System.out.println("------------------------------------------------------------------------------------------");
		histogram.printHastableBySortedKeys();
		System.out.println("------------------------------------------------------------------------------------------");
		histogram.printHashTable(histogram.getWordCount());
	}
}
